/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.core.admin.web.UserMaintainAction
   Module Description   :

   Date Created      : 2009/10/26
   Original Author   : jeff.ma
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.core.admin.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.xwork.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.yaodian100.core.admin.entity.Group;
import com.yaodian100.core.admin.entity.Role;
import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.service.GroupService;
import com.yaodian100.core.admin.service.RoleService;
import com.yaodian100.core.admin.service.UserService;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.menu.entity.Menu;
import com.yaodian100.core.menu.service.MenuService;
import com.yaodian100.ec.common.web.AbstractAction;

/**
 * @author jeff.ma
 * 
 */
public class UserMaintainAction extends AbstractAction {

	/** serialVersionUID */
	private static final long serialVersionUID = 4281715524222814657L;
	/** logger */
	private final Logger logger = LoggerFactory.getLogger(UserMaintainAction.class);
	@Autowired
	private UserService userService;
	@Autowired
	private GroupService groupService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private MenuService menuService;

	private Menu userStatus;
	private List<Role> managerRoles;
	private List<Role> categoryRoles;
	private List<Role> linepmRoles;
	private List<Role> otherRoles;
	private List<Group> groups;

	private String username;
	private String groupCode;

	private User user;
	private String[] grantManageRoles;
	private String[] grantOtherRoles;
	private String[] grantCategoryRoles;
	private String[] grantLinepmRoles;

	/** default constructor */
	public UserMaintainAction() {
	}

	/**
	 * @return the userStatus
	 */
	public Menu getUserStatus() {
		return userStatus;
	}

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @return the groups
	 */
	public List<Group> getGroups() {
		return groups;
	}

	/**
	 * @return the categoryRoles
	 */
	public List<Role> getCategoryRoles() {
		return categoryRoles;
	}

	/**
	 * @return the groupCode
	 */
	public String getGroupCode() {
		return groupCode;
	}

	/**
	 * @param groupCode the groupCode to set
	 */
	public void setGroupCode(String groupCode) {
		this.groupCode = groupCode;
	}

	/**
	 * @return the grantManageRoles
	 */
	public String[] getGrantManageRoles() {
		return grantManageRoles;
	}

	/**
	 * @param grantManageRoles the grantManageRoles to set
	 */
	public void setGrantManageRoles(String[] grantManageRoles) {
		this.grantManageRoles = grantManageRoles;
	}

	/**
	 * @return the grantOtherRoles
	 */
	public String[] getGrantOtherRoles() {
		return grantOtherRoles;
	}

	/**
	 * @param grantOtherRoles the grantOtherRoles to set
	 */
	public void setGrantOtherRoles(String[] grantOtherRoles) {
		this.grantOtherRoles = grantOtherRoles;
	}

	/**
	 * @return the grantCategoryRoles
	 */
	public String[] getGrantCategoryRoles() {
		return grantCategoryRoles;
	}

	/**
	 * @param grantCategoryRoles the grantCategoryRoles to set
	 */
	public void setGrantCategoryRoles(String[] grantCategoryRoles) {
		this.grantCategoryRoles = grantCategoryRoles;
	}

	/**
	 * @return the linepmRoles
	 */
	public List<Role> getLinepmRoles() {
		return linepmRoles;
	}

	/**
	 * @param linepmRoles the linepmRoles to set
	 */
	public void setLinepmRoles(List<Role> linepmRoles) {
		this.linepmRoles = linepmRoles;
	}

	/**
	 * @return the grantLinepmRoles
	 */
	public String[] getGrantLinepmRoles() {
		return grantLinepmRoles;
	}

	/**
	 * @param grantLinepmRoles the grantLinepmRoles to set
	 */
	public void setGrantLinepmRoles(String[] grantLinepmRoles) {
		this.grantLinepmRoles = grantLinepmRoles;
	}

	/**
	 * @return the managerRoles
	 */
	public List<Role> getManagerRoles() {
		return managerRoles;
	}

	/**
	 * @return the otherRoles
	 */
	public List<Role> getOtherRoles() {
		return otherRoles;
	}

	/**
	 * @param username the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	public String view() {
		if (StringUtils.isNotEmpty(username)) {
			try {
				user = userService.get(username);
				if (user == null) {
					addActionError("使用者不存在, 帐号:" + username);
					return "list";
				}
				groupCode = user.getGroupName();
				List<String> mRole = new ArrayList();
				List<String> oRole = new ArrayList();
				List<String> cRole = new ArrayList();
				List<String> lRole = new ArrayList();
				for (Role r : user.getRoles()) {
					switch (r.getType()) {
					case MANAGER:
						mRole.add(r.getName());
						break;
					case OTHER:
						oRole.add(r.getName());
						break;
					case CATEGORY:
						cRole.add(r.getName());
						break;
					case LINEPM:
						lRole.add(r.getName());
						break;
					}
				}
				grantManageRoles = mRole.toArray(new String[0]);
				grantOtherRoles = oRole.toArray(new String[0]);
				grantCategoryRoles = cRole.toArray(new String[0]);
				grantLinepmRoles = lRole.toArray(new String[0]);
			} catch (Exception e) {
				addActionError(e.getMessage());
				e.printStackTrace();
			}
			return "view";
		} else {
			addActionError("使用者不存在, 帐号:" + username);
			return "list";
		}
	}

	public String save() {
		try {
			if (user != null) {
				List<String> userRoleName = new ArrayList();
				Iterator<Role> it = user.getRoles().iterator();
				while (it.hasNext()) {
					Role r = it.next();
					if (Arrays.binarySearch(grantManageRoles, r.getName()) != 0 && Role.Type.MANAGER.equals(r.getType())) {
						// 移除權限為 Manager, 但是代碼不相同
						it.remove();
					} else if (Arrays.binarySearch(grantOtherRoles, r.getName()) != 0 && Role.Type.OTHER.equals(r.getType())) {
						// 移除權限為 Other, 但是代碼不相同
						it.remove();
					} else if (Arrays.binarySearch(grantCategoryRoles, r.getName()) != 0
							&& Role.Type.CATEGORY.equals(r.getType())) {
						// 移除權限為 Category, 但是代碼不相同
						it.remove();
					} else if (Arrays.binarySearch(grantLinepmRoles, r.getName()) != 0 && Role.Type.LINEPM.equals(r.getType())) {
						// 移除權限為 Category, 但是代碼不相同
						it.remove();
					} else if (Role.Type.GROUP.equals(r.getType()) && !r.getKey().equals(groupCode)) {
						// 移除權限為 Group, 但是部門代碼不相同
						it.remove();
					} else {
						userRoleName.add(r.getName());
					}
				}

				for (int i = 0; i < grantManageRoles.length; i++) {
					if (Collections.frequency(userRoleName, grantManageRoles[i]) == 0) {
						logger.info("add role:{}", grantManageRoles[i]);
						Role r = roleService.get(grantManageRoles[i]);
						if (r != null) {
							user.getRoles().add(r);
						}
					}
				}
				for (int i = 0; i < grantOtherRoles.length; i++) {
					if (Collections.frequency(userRoleName, grantOtherRoles[i]) == 0) {
						logger.info("add role:{}", grantOtherRoles[i]);
						Role r = roleService.get(grantOtherRoles[i]);
						if (r != null) {
							user.getRoles().add(r);
						}
					}
				}
				for (int i = 0; i < grantCategoryRoles.length; i++) {
					if (Collections.frequency(userRoleName, grantCategoryRoles[i]) == 0) {
						logger.info("add role:{}", grantCategoryRoles[i]);
						Role r = roleService.get(grantCategoryRoles[i]);
						if (r != null) {
							user.getRoles().add(r);
						}
					}
				}
				for (int i = 0; i < grantLinepmRoles.length; i++) {
					if (Collections.frequency(userRoleName, grantLinepmRoles[i]) == 0) {
						logger.info("add role:{}", grantLinepmRoles[i]);
						Role r = roleService.get(grantLinepmRoles[i]);
						if (r != null) {
							user.getRoles().add(r);
						}
					}
				}

				logger.debug("roles:{}", user.getRoles());
				if (user.getModifyDate() == null) {
					user = userService.createUser(user, null, groupCode);
				} else {
					if (!groupCode.equals(user.getGroupName())) {
						Group newGroup = groupService.get(groupCode);
						user.setGroup(newGroup);
						user.getRoles().add(newGroup.getRole());
					}
					user = userService.save(user);
				}
			} else {
				addActionError("使用者不存在");
				return "list";
			}
		} catch (Exception e) {
			addActionError(e.getMessage());
			e.printStackTrace();
			return "edit";
		}
		return "view";
	}

	public String edit() {
		return "edit";
	}

	public String add() {
		user = new User("");
		return "edit";
	}

	public String delete() {
		try {
			if (user != null) {
				userService.delete(user);
			} else {
				addActionError("使用者不存在, 未删除");
			}
		} catch (Exception e) {
			addActionError(e.getMessage());
			e.printStackTrace();
			return "view";
		}
		return "list";
	}

	public String resetPasswd() {
		try {
			if (user != null) {
				userService.resetPassword(user);
				addActionMessage("重设密码成功");
			}
		} catch (Exception e) {
			addActionError(e.getMessage());
			e.printStackTrace();
			return "view";
		}
		return "view";
	}

	public String list() {
		return "list";
	}

	@Override
	public void prepare() throws Exception {
		super.prepare();
		clearErrorsAndMessages();

		if (userStatus == null) {
			userStatus = menuService.get("User.status");
			logger.debug("new user status:{}", userStatus);
		}

		if (managerRoles == null) {
			CommonCriteria cri = new CommonCriteria();
			cri.addEq("type", Role.Type.MANAGER);
			managerRoles = roleService.getList(0, -1, cri, null);
			for (int i = managerRoles.size(); i > 0; i--) {
				Role r = managerRoles.get(i - 1);
				if (!(r.getKey().startsWith("A-") || r.getKey().startsWith("C"))) {
					managerRoles.remove(i - 1);
				}
			}
		}
		if (categoryRoles == null) {
			CommonCriteria cri = new CommonCriteria();
			cri.addEq("type", Role.Type.CATEGORY);
			categoryRoles = roleService.getList(0, -1, cri, new String[] { "key" });
			Collections.sort(categoryRoles, new RoleComparator());
		}
		if (linepmRoles == null) {
			CommonCriteria cri = new CommonCriteria();
			cri.addEq("type", Role.Type.LINEPM);
			linepmRoles = roleService.getList(0, -1, cri, new String[] { "key" });
			Collections.sort(linepmRoles, new RoleComparator());
		}
		if (otherRoles == null) {
			CommonCriteria cri = new CommonCriteria();
			cri.addEq("type", Role.Type.OTHER);
			otherRoles = roleService.getList(0, -1, cri, new String[] { "key" });
		}
		if (groups == null) {
			CommonCriteria cri = new CommonCriteria();
			cri.addIn("type", Arrays.asList("Y", "C"));
			groups = groupService.getList(0, -1, cri, new String[] { "code asc" });
		}
	}

	public class RoleComparator extends ComparableComparator {
		/** serialVersionUID */
		private static final long serialVersionUID = -7607399952898993734L;

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.apache.commons.collections.comparators.ComparableComparator#compare(java.lang.Object, java.lang.Object)
		 */
		@Override
		public int compare(Object obj1, Object obj2) {
			if (obj1 instanceof Role && obj2 instanceof Role) {
				Role role1 = (Role) obj1;
				Role role2 = (Role) obj2;
				if (NumberUtils.isNumber(role1.getKey()) && NumberUtils.isNumber(role2.getKey())) {
					return Integer.parseInt(role1.getKey()) - Integer.parseInt(role2.getKey());
				} else {
					return role1.getKey().compareTo(role2.getKey());
				}
			} else {
				return super.compare(obj1, obj2);
			}
		}
	}
	
	public RoleComparator getRoleComparator() {
		return new RoleComparator();
	}
}
